package com.donfelix.animationdemo.reveal;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.databinding.DataBindingUtil;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.Toolbar;
import android.transition.Fade;
import android.transition.Transition;
import android.transition.TransitionInflater;
import android.transition.TransitionManager;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.ViewGroup;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.donfelix.animationdemo.R;
import com.donfelix.animationdemo.common.BaseDetailActivity;
import com.donfelix.animationdemo.common.Sample;
import com.donfelix.animationdemo.databinding.ActivityRevealBinding;

/**
 * Created by Don on 2017/3/23.
 * Desc
 */

public class RevealActivity extends BaseDetailActivity implements View.OnClickListener {

    private static final int DELAY = 100;
    private ActivityRevealBinding binding;
    private Sample sample;
    private Interpolator interpolator;
    private RelativeLayout revealRoot;
    private Toolbar toolbar;
    private ImageView sharedTarget;
    private TextView sampleBody;
    private ImageView squareBlue, squareGreen, squareRed, squareYellow;

    @Override
    protected void bindData() {
        binding = DataBindingUtil.setContentView(this, R.layout.activity_reveal);
        sample = (Sample) getIntent().getExtras().getSerializable(EXTRA_SAMPLE);
        binding.setReveal1Sample(sample);
    }

    @Override
    protected void setupWindowAinimation() {
        interpolator = AnimationUtils.loadInterpolator(this, android.R.interpolator.linear_out_slow_in);
        setupEnterAnimations();
        setupExitAnimations();
    }

    @Override
    protected void setupLayout() {
        revealRoot = binding.revealRoot;
        toolbar = binding.toolbar;
        sharedTarget = binding.sharedTarget;
        sampleBody = binding.sampleBody;
        squareBlue = binding.squareBlue;
        squareGreen = binding.squareGreen;
        squareRed = binding.squareRed;
        squareYellow = binding.squareYellow;
        squareBlue.setOnClickListener(this);
        squareGreen.setOnClickListener(this);
        squareRed.setOnClickListener(this);
        squareYellow.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_DOWN) {
                    revealYellow((int) event.getRawX(), (int) event.getRawY());
                }
                return false;
            }
        });
    }

    private void setupEnterAnimations() {
        Transition transition = TransitionInflater.from(this).inflateTransition(R.transition.changebounds_with_arcmotion);
        getWindow().setSharedElementEnterTransition(transition);
        transition.addListener(new Transition.TransitionListener() {
            @Override
            public void onTransitionStart(Transition transition) {
            }

            @Override
            public void onTransitionEnd(Transition transition) {
                transition.removeListener(this);
                sharedTarget.setVisibility(View.GONE);
                animateRevealShow(toolbar);
                animateButtonIn();
            }

            @Override
            public void onTransitionCancel(Transition transition) {
            }

            @Override
            public void onTransitionPause(Transition transition) {
            }

            @Override
            public void onTransitionResume(Transition transition) {
            }
        });
    }

    private void setupExitAnimations() {
        Fade returnTransition = new Fade();
        getWindow().setReturnTransition(returnTransition);
        returnTransition.setDuration(getResources().getInteger(R.integer.anim_duration_medium));
        returnTransition.setStartDelay(getResources().getInteger(R.integer.anim_duration_medium));
        returnTransition.addListener(new Transition.TransitionListener() {
            @Override
            public void onTransitionStart(Transition transition) {
            }

            @Override
            public void onTransitionEnd(Transition transition) {
                transition.removeListener(this);
                animateButtonOut();
                animateRevealHide(revealRoot);
            }

            @Override
            public void onTransitionCancel(Transition transition) {
            }

            @Override
            public void onTransitionPause(Transition transition) {
            }

            @Override
            public void onTransitionResume(Transition transition) {
            }
        });
    }

    private void animateRevealShow(Toolbar toolbar) {
        int cx = (toolbar.getLeft() + toolbar.getRight()) / 2;
        int cy = (toolbar.getTop() + toolbar.getBottom()) / 2;
        int endRadius = Math.max(toolbar.getWidth(), toolbar.getHeight());
        Animator reveal = ViewAnimationUtils.createCircularReveal(toolbar, cx, cy, 0, endRadius);
        toolbar.setVisibility(View.VISIBLE);
        reveal.setDuration(getResources().getInteger(R.integer.anim_duration_long));
        reveal.setInterpolator(new AccelerateInterpolator());
        reveal.start();
    }

    private void animateRevealHide(final RelativeLayout layout) {
        int centerX = (layout.getLeft() + layout.getRight()) / 2;
        int centerY = (layout.getTop() + layout.getBottom()) / 2;
        int startRadius = layout.getWidth();
        Animator reveal = ViewAnimationUtils.createCircularReveal(layout, centerX, centerY, startRadius, 0);
        reveal.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                layout.setVisibility(View.INVISIBLE);
            }
        });
        reveal.setDuration(getResources().getInteger(R.integer.anim_duration_medium));
        reveal.start();
    }

    private void animateButtonIn() {
        for (int i = 0; i < revealRoot.getChildCount(); i++) {
            View child = revealRoot.getChildAt(i);
            child.animate()
                    .setStartDelay(100 + i * DELAY)
                    .setInterpolator(interpolator)
                    .alpha(1f)
                    .scaleX(1f)
                    .scaleY(1f);
        }
    }

    private void animateButtonOut() {
        for (int i = 0; i < revealRoot.getChildCount(); i++) {
            View child = revealRoot.getChildAt(i);
            child.animate()
                    .setStartDelay(i * DELAY)
                    .setInterpolator(interpolator)
                    .alpha(0f)
                    .scaleX(0f)
                    .scaleY(0f);
        }
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.square_blue:
                revealBlue();
                break;
            case R.id.square_green:
                revealGreen();
                break;
            case R.id.square_red:
                revealRed();
                break;
            default:
                break;
        }
    }

    private void revealBlue() {
        animateButtonOut();
        Animator anim = animateRevealColorAnimator(revealRoot, R.color.sample_blue, revealRoot.getWidth() / 2, 0);
        anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                animateButtonIn();
            }
        });
        sampleBody.setText(R.string.reveal_body4);
        sampleBody.setTextColor(ContextCompat.getColor(this, R.color.theme_blue_background));
    }

    private void revealGreen() {
        animateRevealColorAnimator(revealRoot, R.color.sample_green, 0, 0);
        sampleBody.setText(R.string.reveal_body2);
        sampleBody.setTextColor(ContextCompat.getColor(this, R.color.theme_green_background));
    }

    private void revealRed() {
        final ViewGroup.LayoutParams params = squareRed.getLayoutParams();
        Transition transition = TransitionInflater.from(this).inflateTransition(R.transition.changebounds_with_arcmotion);
        transition.addListener(new Transition.TransitionListener() {
            @Override
            public void onTransitionStart(Transition transition) {
            }

            @Override
            public void onTransitionEnd(Transition transition) {
                animateRevealColorAnimator(revealRoot, R.color.sample_red, 0, 0);
                sampleBody.setText(R.string.reveal_body3);
                sampleBody.setTextColor(ContextCompat.getColor(RevealActivity.this, R.color.theme_red_background));
                squareRed.setLayoutParams(params);
            }

            @Override
            public void onTransitionCancel(Transition transition) {
            }

            @Override
            public void onTransitionPause(Transition transition) {
            }

            @Override
            public void onTransitionResume(Transition transition) {
            }
        });
        TransitionManager.beginDelayedTransition(revealRoot, transition);
        RelativeLayout.LayoutParams layoutParams =
                new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
        layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
        squareRed.setLayoutParams(layoutParams);
    }

    private void revealYellow(int x, int y) {
        animateRevealColorAnimator(revealRoot, R.color.sample_yellow, x, y);
        sampleBody.setText(R.string.reveal_body1);
        sampleBody.setTextColor(ContextCompat.getColor(this, R.color.theme_yellow_background));
    }

    private Animator animateRevealColorAnimator(ViewGroup root, int color, int x, int y) {
        int centerX = (root.getLeft() + root.getRight()) / 2;
        int centerY = (root.getTop() + root.getBottom()) / 2;
        float endRadius = (float) Math.hypot(root.getWidth(), root.getHeight());
        Animator anim = null;
        if (y == 0) {
            anim = ViewAnimationUtils.createCircularReveal(root, x, y, 0, endRadius);
        } else {
            anim = ViewAnimationUtils.createCircularReveal(root, centerX, centerY, 0, endRadius);
        }
        root.setBackgroundColor(ContextCompat.getColor(this, color));
        anim.setDuration(getResources().getInteger(R.integer.anim_duration_long));
        anim.setInterpolator(new AccelerateDecelerateInterpolator());
        anim.start();
        return anim;
    }
}
